package org.developer.apidemo.common;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.developer.apidemo.util.MD5Util;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

@Data
@Slf4j
public class ApiResponse<T> {

    private ApiResult result;

    private T data;

    private String sign;

    public static <T> ApiResponse success(T data){
        return response(ApiCodeEnum.SUCCESS.getCode(),ApiCodeEnum.SUCCESS.getMsg(),data);
    }

    public static ApiResponse error(String code, String msg) {
        return response(code, msg, null);
    }

    public static <T> ApiResponse response(String code, String msg, T data){
        ApiResult result = new ApiResult(code, msg);
        ApiResponse response = new ApiResponse();

        response.setData(data);
        response.setResult(result);

        String sign = signData(data);
        response.setSign(sign);

        return response;
    }

    private static <T> String signData(T data){
        String key = "12345678954556";
        Map<String,String> responseMap = null;

        try {
            responseMap = getFields(data);
        } catch (IllegalAccessException e) {

            return null;
        }
        String urlComponent = ApiUtil.concatSignString(responseMap);
        String signature = urlComponent + "key=" + key;
        String sign = MD5Util.encode(signature);

        return sign;
    }

    public static Map<String,String> getFields(Object data) throws IllegalAccessException {
        if(data == null) return null;

        Map<String,String> map = new HashMap();

        Field[] fields = data.getClass().getDeclaredFields();
        for(int i=0; i<fields.length;i++){
            Field field = fields[i];
            field.setAccessible(true);

            String name = field.getName();
            Object value = field.get(data);
            if (field.get(data) != null) {
                map.put(name, value.toString());
            }
        }

        return map;
    }
}
